From 859fa39e18dcf534842623251bd62635a582558f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 24 Nov 2014 21:34:05 -0800 Subject: [PATCH] Support documenting a selective package --- src/bin/doc.rs | 25 +++++++++++++-------- src/cargo/ops/cargo_doc.rs | 46 ++++++++++++++++++++++++-------------- tests/test_cargo_doc.rs | 38 +++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 26 deletions(-) diff --git a/src/bin/doc.rs b/src/bin/doc.rs index b94ec30e3..6e835ed51 100644 --- a/src/bin/doc.rs +++ b/src/bin/doc.rs @@ -12,6 +12,7 @@ struct Options { flag_no_deps: bool, flag_open: bool, flag_verbose: bool, + flag_package: Option, } pub const USAGE: &'static str = " @@ -21,17 +22,23 @@ Usage: cargo doc [options] Options: - -h, --help Print this message - --open Opens the docs in a browser after the operation - --no-deps Don't build documentation for dependencies - -j N, --jobs N The number of jobs to run in parallel - --features FEATURES Space-separated list of features to also build - --no-default-features Do not build the `default` feature - --manifest-path PATH Path to the manifest to document - -v, --verbose Use verbose output + -h, --help Print this message + --open Opens the docs in a browser after the operation + -p SPEC, --package SPEC Package to document + --no-deps Don't build documentation for dependencies + -j N, --jobs N The number of jobs to run in parallel + --features FEATURES Space-separated list of features to also build + --no-default-features Do not build the `default` feature + --manifest-path PATH Path to the manifest to document + -v, --verbose Use verbose output By default the documentation for the local package and all dependencies is built. The output is all placed in `target/doc` in rustdoc's usual format. + +If the --package argument is given, then SPEC is a package id specification +which indicates which package should be documented. If it is not given, then the +current package is documented. For more information on SPEC and its format, see +the `cargo help pkgid` command. "; pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult> { @@ -50,7 +57,7 @@ pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult dev_deps: false, features: options.flag_features.as_slice(), no_default_features: options.flag_no_default_features, - spec: None, + spec: options.flag_package.as_ref().map(|s| s.as_slice()), lib_only: false }, }; diff --git a/src/cargo/ops/cargo_doc.rs b/src/cargo/ops/cargo_doc.rs index 2a34f7fd4..2e7831440 100644 --- a/src/cargo/ops/cargo_doc.rs +++ b/src/cargo/ops/cargo_doc.rs @@ -1,5 +1,7 @@ +use std::io::fs::PathExtensions; use std::collections::HashSet; +use core::PackageIdSpec; use core::source::Source; use ops; use sources::PathSource; @@ -20,31 +22,41 @@ pub fn doc(manifest_path: &Path, let mut lib_names = HashSet::new(); let mut bin_names = HashSet::new(); - for target in package.get_targets().iter().filter(|t| t.get_profile().is_doc()) { - if target.is_lib() { - assert!(lib_names.insert(target.get_name())); - } else { - assert!(bin_names.insert(target.get_name())); + if options.compile_opts.spec.is_none() { + for target in package.get_targets().iter().filter(|t| t.get_profile().is_doc()) { + if target.is_lib() { + assert!(lib_names.insert(target.get_name())); + } else { + assert!(bin_names.insert(target.get_name())); + } } - } - for bin in bin_names.iter() { - if lib_names.contains(bin) { - return Err(human("Cannot document a package where a library and a \ - binary have the same name. Consider renaming one \ - or marking the target as `doc = false`")) + for bin in bin_names.iter() { + if lib_names.contains(bin) { + return Err(human("Cannot document a package where a library \ + and a binary have the same name. Consider \ + renaming one or marking the target as \ + `doc = false`")) + } } } try!(ops::compile(manifest_path, &mut options.compile_opts)); if options.open_result { - use std::io::fs::PathExtensions; + let name = match options.compile_opts.spec { + Some(spec) => try!(PackageIdSpec::parse(spec)).get_name().to_string(), + None => { + match lib_names.iter().nth(0) { + Some(s) => s.to_string(), + None => return Ok(()) + } + } + }; - match lib_names.iter().nth(0).map(|l| package.get_absolute_target_dir() - .join("doc").join(*l).join("index.html")) - { - Some(ref path) if path.exists() => open_docs(path), - _ => () + let path = package.get_absolute_target_dir().join("doc").join(name) + .join("index.html"); + if path.exists() { + open_docs(&path); } } diff --git a/tests/test_cargo_doc.rs b/tests/test_cargo_doc.rs index 3f74f9282..60525f586 100644 --- a/tests/test_cargo_doc.rs +++ b/tests/test_cargo_doc.rs @@ -206,3 +206,41 @@ Cannot document a package where a library and a binary have the same name. \ Consider renaming one or marking the target as `doc = false` ")); }) + +test!(doc_dash_p { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies.a] + path = "a" + "#) + .file("src/lib.rs", "extern crate a;") + .file("a/Cargo.toml", r#" + [package] + name = "a" + version = "0.0.1" + authors = [] + + [dependencies.b] + path = "../b" + "#) + .file("a/src/lib.rs", "extern crate b;") + .file("b/Cargo.toml", r#" + [package] + name = "b" + version = "0.0.1" + authors = [] + "#) + .file("b/src/lib.rs", ""); + + assert_that(p.cargo_process("doc").arg("-p").arg("a"), + execs().with_status(0) + .with_stdout(format!("\ +{compiling} b v0.0.1 (file://[..]) +{compiling} a v0.0.1 (file://[..]) +", compiling = COMPILING).as_slice())); +}) -- 2.30.2